<?php

/**
 *
 * 数据基本操作基类
 *
 * @author: hjh <hjh@jf.com>
 *
 * Date: 2017/3/6
 * Time: 14:26
 */

namespace Common;

class DBModelBase
{
    /**
     * 以下需要在 继承类中重新定义
     */
    //memcache相关
    protected static $MEMCACHE = null;
    protected static $MC_SINGLE_KEY = null; //单个key
    protected static $MC_EXPIRE = 7200;

    //mysql db 相关
    protected static $DB_WRITE = null;
    protected static $DB_READ = null;

    //本地缓存
    protected static $_CACHE = null;

    //表名
    protected static $TABLE_NAME = null;
    //主键id
    protected static $PRIMARY_ID = null;

    //表结构
    protected static $_FIELDS = null;

    /**
     * 通过主键id 获取数据
     *
     * @param string $id 主键id
     * @param bool $cache 是否从缓存读取
     * @return mixed|null|string
     */
    public static function getDataInfoById($id, $cache = true)
    {
        static::checkAssert();

        $id = (int)$id;
        if ($cache) {
            if (isset(static::$_CACHE[$id])) {
                return static::$_CACHE[$id];
            }
            $data = static::getMc()->get(static::getMcSingleKey($id));
            if (!empty($data)) {
                return $data;
            }
        }

        $data = static::getPdo()->select('*')->from(static::$TABLE_NAME)->where([static::$PRIMARY_ID => $id])->getOne();
        if ($data) {
            static::$_CACHE[$id] = $data;
            static::getMc()->set(static::getMcSingleKey($id), $data, static::$MC_EXPIRE);
        }

        return $data;
    }

    /**
     * 根据id列表获取数据
     *
     * @param array $ids id 列表
     * @return array|bool|string
     */
    public static function getDataListByIds($ids)
    {
        static::checkAssert();

        $need_load_from_mc = [];
        $data = [];
        $diff_id = [];
        foreach ($ids as $id) {

            $id = (int)$id;

            if (isset(static::$_CACHE[$id])) {
                $data[$id] = static::$_CACHE[$id];
            } else {
                $diff_id[$id] = $id;
                $need_load_from_mc[] = static::getMcSingleKey($id);
            }
        }

        if (count($diff_id) > 0) {
            $res = static::getMc()->get($need_load_from_mc);
            if (is_array($res) && count($res) > 0) {
                foreach ($res as $id => $dataInfo) {

                    $id = (int)$id;

                    static::$_CACHE[$id] = $dataInfo;
                    $data[$id] = $dataInfo;

                    unset($diff_id[$id]);
                }
            }
        }

        if (count($diff_id) > 0) {
            $ids_pdo = implode(',', array_values($diff_id));
            $res = static::getPdo()->select('*')->from(static::$TABLE_NAME)->where([static::$PRIMARY_ID . ' IN' => $ids_pdo])->getAll();
            if (is_array($res) && count($res) > 0) {
                foreach ($res as $dataInfo) {
                    $id = (int)$dataInfo[static::$PRIMARY_ID];

                    static::$_CACHE[$id] = $dataInfo;
                    $data[$id] = $dataInfo;

                    unset($diff_id[$id]);
                }
            }
        }

        if (count($diff_id) > 0) {
            debug_log(['getRadioInfoListByIds not found', $diff_id, static::$TABLE_NAME], JF_LOG_ERROR);
        }

        //按传进来的值进行排序
        $res = [];
        foreach ($ids as $id) {
            $id = (int)$id;
            if (isset($data[$id])) {
                $res[$id] = $data[$id];
            }
        }
        return $res;
    }

    /**
     * 更新数据
     * @param $id
     * @param $row
     * @param $un_alterable
     * @param array $extraWhere 额外的条件
     * @return bool
     */
    public static function updateData($id, $row, $un_alterable, $extraWhere = [])
    {
        $data = DataType::dataCheck($row, static::$_FIELDS);
        if (empty($data)) {
            return false;
        }
        $intersect_key = array_intersect_key($data, $un_alterable);
        if (count($intersect_key) > 0) {
            debug_log(['updateData', static::$TABLE_NAME, 'contain unalterable key', $row]);
            return false;
        }
        $extraWhere[static::$PRIMARY_ID] = $id;

        $res = static::getPdo(true)->update(static::$TABLE_NAME, $data, $extraWhere);
        if ($res) {
            static::getMc()->delete(static::getMcSingleKey($id));
        }
        return $res;
    }

    /**
     * 修改计数型数据
     *
     * @param       $id
     * @param       $row
     * @param       $unAlterable
     * @param array $extraWhere
     * @return bool
     */
    public static function updateCountData($id, $row, $unAlterable, $extraWhere = [])
    {
        foreach ($row as $key => $value) {
            if (!is_array($value)) {
                return false;
            }
        }
        $intersect_key = array_intersect_key($row, $unAlterable);
        if (count($intersect_key) > 0) {
            debug_log(['updateData', static::$TABLE_NAME, 'contain unalterable key', $row]);
            return false;
        }
        $extraWhere[static::$PRIMARY_ID] = $id;

        $res = static::getPdo(true)->update(static::$TABLE_NAME, $row, $extraWhere);
        if ($res) {
            static::getMc()->delete(static::getMcSingleKey($id));
        }
        return $res;
    }

    /**
     * 删除单个数据缓存
     *
     * @param $id
     * @return bool|int
     */
    public static function deleteData($id)
    {
        $res = static::getPdo(true)->delete(static::$TABLE_NAME, [static::$PRIMARY_ID => $id]);
        if ($res) {
            static::getMc()->delete(static::getMcSingleKey($id));
        }
        return $res;
    }

    /**
     * 格式化添加数据
     *
     * @param $row
     * @param $required
     * @return array|bool
     */
    protected static function formatAddData($row, $required)
    {
        $data = DataType::dataCheck((array)$row, static::$_FIELDS);
        $diff_key = array_diff_key($required, $data);
        if (count($diff_key) > 0) {
            debug_log(['formatAddData', static::$TABLE_NAME, $diff_key], JF_LOG_ERROR);
            return false;
        }
        return $data;
    }

    /**
     * 获取mc链接对象
     * @return \lib\plugins\cache\Memcached
     */
    protected static function getMc()
    {
        assert(!is_null(static::$MEMCACHE));

        return Bridge::memcache(static::$MEMCACHE);
    }

    /**
     * 获取Pdo操作对象
     * @param bool $write
     * @return \lib\plugins\pdo\PDOQuery|PDOStatement
     */
    protected static function getPdo($write = false)
    {
        assert(!is_null(static::$DB_WRITE) && !is_null(static::$DB_READ));

        return Bridge::pdo($write ? static::$DB_WRITE : static::$DB_READ);
    }

    /**
     * 获取单个 mc key
     * @param string $id 主键id
     * @return string
     */
    protected static function getMcSingleKey($id)
    {
        assert(!is_null(static::$MC_SINGLE_KEY));
        $key = sprintf(static::$MC_SINGLE_KEY, $id);
//        var_dump($key);die;
        return $key;
    }

    protected static function checkAssert()
    {
        assert(!is_null(static::$MEMCACHE)
            && !is_null(static::$MC_SINGLE_KEY)
            && !is_null(static::$DB_WRITE)
            && !is_null(static::$DB_READ)
            && !is_null(static::$_CACHE)
            && !is_null(static::$TABLE_NAME)
            && !is_null(static::$PRIMARY_ID)
            && !is_null(static::$_FIELDS));
    }

    public static function checkMobile($mobile)
    {
        if (!preg_match('/^1[0-9]{10}$/', $mobile)) {
            return false;
        }
        return true;
    }
}